package com.zaizai.utils;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.util.List;

/**
 * Excel相关处理
 *
 * @author zaizai
 */
public class ExcelUtil<T> {
    private static final Logger logger = LoggerFactory.getLogger(ExcelUtil.class);

    /**
     * 实体对象
     */
    public Class<T> clazz;

    public ExcelUtil(Class<T> clazz) {
        this.clazz = clazz;
    }

    /**
     * 对list数据源将其里面的数据导入到excel表单（EasyExcel）
     *
     * @param response  响应对象
     * @param list      导出数据集合
     * @param sheetName 工作表的名称
     */
    public void exportEasyExcel(HttpServletResponse response, List<T> list, String sheetName) {
        try (OutputStream outputStream = response.getOutputStream()) {
            // 将指定数据写入到Excel文件中
            EasyExcel.write(outputStream, clazz).sheet(sheetName).doWrite(list);
        } catch (IOException e) {
            // 记录异常信息
            logger.error("导出EasyExcel异常: {}", e.getMessage(), e);
        }
    }


    /**
     * 导出包含嵌套 List 属性的 Excel 文件
     *
     * @param response   HttpServletResponse
     * @param list       数据列表
     * @param sheetName1 第一个工作表的名称
     * @param sheetName2 第二个工作表的名称
     * @param <T>        泛型类型
     */
    public <T> void exportEasyExcel(HttpServletResponse response, List<T> list, String sheetName1, String sheetName2) {
        if (list == null || list.isEmpty()) {
            return;
        }

        try {
            OutputStream outputStream = response.getOutputStream();
            // 创建 ExcelWriter
            ExcelWriter excelWriter = EasyExcel.write(outputStream).build();

            // 写入第一个工作表，包含泛型对象的所有属性（除了列表属性）
            WriteSheet writeSheet1 = EasyExcel.writerSheet(0, sheetName1).head(clazz).build();
            excelWriter.write(list, writeSheet1);

            // 反射获取包含 List 类型属性的对象
            Field listField = null;
            for (Field field : clazz.getDeclaredFields()) {
                if (List.class.isAssignableFrom(field.getType())) {
                    listField = field;
                    break;
                }
            }

            if (listField != null) {
                listField.setAccessible(true); // 私有属性也可以访问

                // 获取列表中元素的类型
                Class<?> listElementType = getGenericType(listField.getGenericType());
                if (listElementType != null) {
                    // 写入 Excel 的第二个工作表
                    WriteSheet writeSheet2 = EasyExcel.writerSheet(1, sheetName2).head(listElementType).build();

                    // 遍历数据，获取列表字段中的数据，并写入第二个工作表
                    for (T data : list) {
                        Object listData = listField.get(data);
                        if (listData instanceof List) {
                            excelWriter.write((List<?>) listData, writeSheet2);
                        }
                    }
                }
            }

            // 关闭 ExcelWriter
            excelWriter.finish();
        } catch (IOException e) {
            // 处理导出过程中可能发生的 IO 异常
            System.out.println("导出EasyExcel异常：" + e.getMessage());
        } catch (IllegalAccessException e) {
            System.out.println("访问私有属性异常：" + e.getMessage());
        }
    }

    /**
     * 获取字段的泛型类型
     *
     * @param genericType 字段的泛型类型
     * @return 泛型类型的 Class
     */
    private Class<?> getGenericType(java.lang.reflect.Type genericType) {
        if (genericType instanceof java.lang.reflect.ParameterizedType) {
            java.lang.reflect.ParameterizedType parameterizedType = (java.lang.reflect.ParameterizedType) genericType;
            // 返回泛型参数类型
            return (Class<?>) parameterizedType.getActualTypeArguments()[0];
        }
        return null;
    }
}
